#!/usr/bin/env python3
"""
查找自定义Base64字符表
"""

import subprocess
import re

def find_base64_charset():
    """在Lingma二进制中查找自定义Base64字符表"""
    print("🔍 === 查找自定义Base64字符表 ===\n")
    
    # 我们的字符集
    our_charset = "!#%&()*,.@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_abcdefghijklmnopqrstuvwxyz"
    print(f"目标字符集: {our_charset}")
    print(f"字符集长度: {len(our_charset)}")
    
    # 标准Base64字符集
    std_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    
    # 1. 查找包含特殊字符的字符串
    print("\n1. 查找包含特殊字符的字符串:")
    special_chars = "!#%&()*,.@^_"
    
    try:
        # 使用strings查找包含多个特殊字符的字符串
        result = subprocess.run(['strings', '-n', '20', 'Lingma'], 
                              capture_output=True, text=True)
        strings = result.stdout.strip().split('\n')
        
        candidates = []
        for s in strings:
            # 计算包含多少个特殊字符
            special_count = sum(1 for c in s if c in special_chars)
            # 计算包含多少个字母
            letter_count = sum(1 for c in s if c.isalpha())
            
            # 如果包含多个特殊字符和字母，可能是字符表
            if special_count >= 5 and letter_count >= 20 and len(s) <= 100:
                candidates.append((s, special_count))
        
        # 按特殊字符数排序
        candidates.sort(key=lambda x: x[1], reverse=True)
        
        print(f"找到 {len(candidates)} 个候选字符串:")
        for s, count in candidates[:10]:
            print(f"  特殊字符{count}个: {s[:80]}...")
    except:
        pass
    
    # 2. 查找字符集的片段
    print("\n2. 查找字符集片段:")
    
    # 尝试查找字符集的不同片段
    fragments = [
        "!#%&()*",     # 开头
        ",.@ABC",      # 中间
        "xyz",         # 结尾
        "^_abc",       # 中间过渡
        "@ABCDEFGHIJK", # 大写字母部分
    ]
    
    for fragment in fragments:
        print(f"\n查找片段: {fragment}")
        try:
            # 使用grep查找包含这个片段的位置
            result = subprocess.run(['grep', '-abo', fragment, 'Lingma'],
                                  capture_output=True, text=True)
            if result.stdout:
                lines = result.stdout.strip().split('\n')
                print(f"  找到 {len(lines)} 处:")
                for line in lines[:3]:
                    offset = line.split(':')[0]
                    print(f"    偏移: {offset}")
                    
                    # 查看这个位置附近的内容
                    hex_result = subprocess.run(
                        ['hexdump', '-C', '-s', offset, '-n', '128', 'Lingma'],
                        capture_output=True, text=True
                    )
                    if hex_result.stdout:
                        print("    附近内容:")
                        for hex_line in hex_result.stdout.split('\n')[:3]:
                            if hex_line:
                                print(f"      {hex_line}")
        except:
            pass
    
    # 3. 查找字符映射表
    print("\n3. 查找可能的字符映射:")
    
    # 计算我们的字符集和标准Base64的差异
    our_set = set(our_charset)
    std_set = set(std_base64)
    
    only_in_ours = our_set - std_set
    only_in_std = std_set - our_set
    
    print(f"\n只在我们字符集中的: {''.join(sorted(only_in_ours))}")
    print(f"只在标准Base64中的: {''.join(sorted(only_in_std))}")
    
    # 4. 在二进制中搜索完整的64字符序列
    print("\n4. 搜索64字符序列:")
    
    try:
        # 提取所有64字符长度的字符串
        result = subprocess.run(['strings', '-n', '64', '-t', 'x', 'Lingma'],
                              capture_output=True, text=True)
        lines = result.stdout.strip().split('\n')
        
        for line in lines:
            if ' ' in line:
                offset, string = line.split(' ', 1)
                if len(string) == 64:
                    # 检查是否可能是字符表
                    unique_chars = len(set(string))
                    if unique_chars >= 60:  # 大部分字符都是唯一的
                        print(f"\n  偏移 {offset}: {string}")
                        print(f"    唯一字符数: {unique_chars}")
                        
                        # 检查是否包含我们的特殊字符
                        our_special = sum(1 for c in string if c in "!#%&()*,.@^_")
                        if our_special > 0:
                            print(f"    包含特殊字符: {our_special}个")
    except:
        pass

def search_encoding_logic():
    """搜索编码逻辑"""
    print("\n\n🔍 === 搜索编码逻辑 ===")
    
    # 搜索Base64相关的符号
    try:
        result = subprocess.run(['nm', '-D', 'Lingma'], 
                              capture_output=True, text=True)
        if result.stdout:
            lines = result.stdout.strip().split('\n')
            base64_symbols = [l for l in lines if 'base64' in l.lower() or 'b64' in l.lower()]
            
            if base64_symbols:
                print("\n找到Base64相关符号:")
                for sym in base64_symbols[:10]:
                    print(f"  {sym}")
    except:
        pass
    
    # 使用objdump查找Base64相关函数
    try:
        result = subprocess.run(['objdump', '-T', 'Lingma'],
                              capture_output=True, text=True)
        if result.stdout:
            lines = result.stdout.strip().split('\n')
            encoding_funcs = [l for l in lines if any(k in l.lower() for k in ['encode', 'decode', 'base64', 'transform'])]
            
            if encoding_funcs:
                print("\n找到编码相关函数:")
                for func in encoding_funcs[:10]:
                    print(f"  {func}")
    except:
        pass

def analyze_binary_sections():
    """分析二进制的各个段"""
    print("\n\n📊 === 分析二进制段 ===")
    
    try:
        # 查看二进制的段信息
        result = subprocess.run(['readelf', '-S', 'Lingma'],
                              capture_output=True, text=True)
        if result.stdout:
            print("段信息:")
            lines = result.stdout.strip().split('\n')
            for line in lines:
                if any(s in line for s in ['.rodata', '.data', '.text']):
                    print(f"  {line}")
    except:
        pass

if __name__ == "__main__":
    find_base64_charset()
    search_encoding_logic()
    analyze_binary_sections()
    
    print("\n\n💡 === 分析建议 ===")
    print("基于搜索结果：")
    print("1. 自定义Base64字符表可能是动态生成的")
    print("2. 可能使用了标准Base64库但映射了不同的字符")
    print("3. 加密可能分多步：")
    print("   a. 原始数据 → 某种加密/编码")
    print("   b. 结果 → 自定义Base64编码")
    print("4. 需要通过动态调试来捕获运行时的字符映射表")